#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include "Thread.hpp"
#include "Logger.hpp"
#include "Cond.hpp"

const static int defaultnum = 5;

template <class T>
class ThreadPool
{
private:
    bool Isempty()
    {
        return _queue.empty();
    }
    void Routine(const std::string &name)
    {
        while (true)
        {
            T t;
            {
                LockGuarden lockguard(&_lock);
                while (Isempty() && _isrunning)
                {
                    ++_wait_thread_num;
                    _cond.Wait(&_lock);
                    --_wait_thread_num;
                }
                if (!_isrunning && Isempty())
                {
                    LOG(LogLevel::INFO) << "线程池退出&&任务队列为空";
                    break;
                }
                t = _queue.front();
                std::cout << t << std::endl;
                _queue.pop();
            }
            // 这里执行t的任务
            LOG(LogLevel::INFO) << name << "执行任务成功";
        }
    }

public:
    ThreadPool(int thread_num = defaultnum)
        : _thread_num(thread_num), _wait_thread_num(0), _isrunning(false)
    {
        for (int i = 0; i < _thread_num; i++)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            _threads.emplace_back([this](const std::string&name){ this->Routine(name); }, name);
        }
        LOG(LogLevel::INFO) << "线程创建成功";
    }

    void Start()
    {
        if (_isrunning)
            return;
        _isrunning = true;
        for (auto &e : _threads)
        {
            e.Start();
        }
        LOG(LogLevel::INFO) << "线程启动成功";
    }

    void EnQueue(const T &in)
    {
        if (!_isrunning)
            return;
        {
            LockGuarden lockguard(&_lock);
            _queue.push(in);
            if (_wait_thread_num)
            {
                _cond.RouseSignal();
            }
        }
    }

    void Wait()
    {
        for (auto &e : _threads)
        {
            e.Join();
        }
        LOG(LogLevel::INFO) << "线程等待成功";
    }
    void Stop()
    {
        if (!_isrunning)
            return;
        _isrunning = false;
        if (_wait_thread_num)
            _cond.RouseAll();
    }
    ~ThreadPool() {}

private:
    std::queue<T> _queue;
    std::vector<Thread> _threads;
    int _thread_num;
    int _wait_thread_num;
    Mutex _lock;
    Cond _cond;

    bool _isrunning;
};